package baseFx.common.services;

import baseFx.common.EventDispatcher;

import java.util.*;

public abstract class AbstractServiceContext implements ServiceContext {
    private Map<String, Object> userdata = new HashMap<>();
    private static final String beforeDispatcherKey = UUID.randomUUID().toString();
    private static final String afterDispatcherKey = UUID.randomUUID().toString();
    private static final String errorDispatcherKey = UUID.randomUUID().toString();
    private EventDispatcher<ServiceObjectArgs> beforeDispatcher = new EventDispatcher<>(beforeDispatcherKey);
    private EventDispatcher<ServiceObjectArgs> afterDispatcher = new EventDispatcher<>(afterDispatcherKey);
    private EventDispatcher<ServiceObjectErrorArgs> errorDispatcher = new EventDispatcher<>(errorDispatcherKey);

    @Override
    public EventDispatcher<ServiceObjectArgs> eventAfter() {
        return afterDispatcher;
    }

    @Override
    public EventDispatcher<ServiceObjectArgs> eventBefore() {
        return beforeDispatcher;
    }

    @Override
    public EventDispatcher<ServiceObjectErrorArgs> eventError() {
        return errorDispatcher;
    }

    protected void onBefore(ServiceObjectArgs e) {
        beforeDispatcher.fire(beforeDispatcherKey, this, e);
    }

    protected void onAfter(ServiceObjectArgs e) {
        afterDispatcher.fire(afterDispatcherKey, this, e);
    }

    protected void onError(ServiceObjectErrorArgs e) {
        errorDispatcher.fire(errorDispatcherKey, this, e);
    }

    @Override
    public Map<String, Object> getUserdata() {
        return userdata;
    }

    @Override
    public void close() {
        if (userdata != null) {
            userdata.clear();
            userdata = null;
        }
        if (beforeDispatcher != null) {
            beforeDispatcher.clear();
            beforeDispatcher = null;
        }
        if (afterDispatcher != null) {
            afterDispatcher.clear();
            afterDispatcher = null;
        }
        if (errorDispatcher != null) {
            errorDispatcher.clear();
            errorDispatcher = null;
        }
    }

    protected void executeSo(ServiceObject so, Object state) {
        so.onExecute(this, state);
    }
}
